/**
 * nghilt
 * 2011/09/13
 */
package vn.nnn.shogi.board;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import at.com.vn.chess.util.Const;
import at.com.vn.chess.util.RectangleUtils;

import vn.nnn.shogi.quanco.QuanCo;

/**
 * 
 */
public class Board {

	private Rectangle[][] board;
	private Rectangle[][] realBoard;
	private Rectangle[][] activeBoard;
	private Rectangle[][] vungBatQuanCuaQuanDen;
	private Rectangle[][] vungBatQuanCuaQuanTrang;
	private Rectangle[][] vungPhongQuanDen;
	private Rectangle[][] vungPhongQuanTrang;

	private Rectangle[][] vungGhiSoLuongTuBinhCuaQuanDen;
	private Rectangle[][] vungGhiSoLuongTuBinhCuaQuanTrang;

	private Point historyButtonLocation;
	private Point privateChatLocation;
	
	private Rectangle[][] vungBatQuan;
	private Rectangle[][] vungGhiSoLuongTuBinh;
	int[][] soLuongTuBinh;

	/**
	 * Mang co 3 phan tu [0]: Vi tri ten nguoi choi [1]: Vi tri dong ho
	 */
	Rectangle[] vungThongTinQuanTrang;

	/**
	 * Mang co 3 phan tu [0]: Vi tri ten nguoi choi [1]: Vi tri dong ho
	 */
	Rectangle[] vungThongTinQuanDen;

	int[][] soLuongTuBinhCuaDen;
	int[][] soLuongTuBinhCuaTrang;
	
	private Dimension boardSize;

	public Board( Dimension size ) {
		
		boardSize = size;

		board = new Rectangle[Const.GLOBAL_BOARD_ROW][Const.GLOBAL_BOARD_COL];
		realBoard = new Rectangle[Const.REAL_BOARD_ROW][Const.REAL_BOARD_COL];
		activeBoard = new Rectangle[Const.ACTIVE_BOARD_ROW][Const.ACTIVE_BOARD_COL];
		
		vungBatQuanCuaQuanDen = new Rectangle[Const.VUNG_BAT_QUAN_ROW][Const.VUNG_BAT_QUAN_COL];
		vungBatQuanCuaQuanTrang = new Rectangle[Const.VUNG_BAT_QUAN_ROW][Const.VUNG_BAT_QUAN_COL];
		vungGhiSoLuongTuBinhCuaQuanDen = new Rectangle[Const.VUNG_BAT_QUAN_ROW][Const.VUNG_BAT_QUAN_COL];
		vungGhiSoLuongTuBinhCuaQuanTrang = new Rectangle[Const.VUNG_BAT_QUAN_ROW][Const.VUNG_BAT_QUAN_COL];
		
		vungPhongQuanDen = new Rectangle[Const.VUNG_PHONG_QUAN_ROW][Const.REAL_BOARD_COL];
		vungPhongQuanTrang = new Rectangle[Const.VUNG_PHONG_QUAN_ROW][Const.REAL_BOARD_COL];
		
		soLuongTuBinhCuaDen = new int[Const.VUNG_BAT_QUAN_ROW][Const.VUNG_BAT_QUAN_COL];
		soLuongTuBinhCuaTrang = new int[Const.VUNG_BAT_QUAN_ROW][Const.VUNG_BAT_QUAN_COL];

		vungBatQuan = new Rectangle[6][Const.VUNG_BAT_QUAN_COL];
		vungGhiSoLuongTuBinh = new Rectangle[6][Const.VUNG_BAT_QUAN_COL];
		soLuongTuBinh = new int[6][Const.VUNG_BAT_QUAN_COL];
		
		vungThongTinQuanTrang = new Rectangle[2];
		vungThongTinQuanDen = new Rectangle[2];

		Point toaDo;
		Dimension kichThuocOCo = new Dimension( size.width
				/ Const.GLOBAL_BOARD_COL, size.height / Const.GLOBAL_BOARD_ROW );
		Rectangle oCo;

		int row = 0, col = 0;
		
		// Toan bo giao dien ban co
		for ( row = 0; row < Const.GLOBAL_BOARD_ROW; row++ ) {
			for ( col = 0; col < Const.GLOBAL_BOARD_COL; col++ ) {
				toaDo = new Point( col * kichThuocOCo.width, row
						* kichThuocOCo.height );
				oCo = new Rectangle( toaDo, kichThuocOCo );
				board[row][col] = oCo;
			}
		}
		
		// Giao dien ban co ( tru khung chat )
		for ( row = 0; row < Const.ACTIVE_BOARD_ROW; row++ ) {
			for ( col = 0; col < Const.ACTIVE_BOARD_COL; col++ ) {
				activeBoard[row][col] = board[row + 1][col];
			}
		}

		// Ban co thuc
		for ( row = 0; row < Const.REAL_BOARD_ROW; row++ ) {
			for ( col = 0; col < Const.REAL_BOARD_COL; col++ ) {
				realBoard[row][col] = board[row + 1][col + 4];
			}
		}		

		// Vung bat quan 1
		for ( row = 0; row < Const.VUNG_BAT_QUAN_ROW; row++ ) {
			for ( col = 0; col < Const.VUNG_BAT_QUAN_COL; col++ ) {
				vungBatQuanCuaQuanTrang[row][col] = board[row + 1][col];

				vungGhiSoLuongTuBinhCuaQuanTrang[row][col] = getVungGhiSoLuongTuBinhCuaQuanTrang( vungBatQuanCuaQuanTrang[row][col] );

				// Lay vung bat quan den cua quan trang
				vungBatQuanCuaQuanDen[row][col] = board[row + 7][col + 14];

				vungGhiSoLuongTuBinhCuaQuanDen[row][col] = getVungGhiSoLuongTuBinhCuaQuanDen( vungBatQuanCuaQuanDen[row][col] );
				
			}
		}
		
		// Vung bat quan 2
		for ( row = 0; row < 6; row++ ) {
			for ( col = 0; col < Const.VUNG_BAT_QUAN_COL; col++ ) {
				if( row < 3 ) {
					vungBatQuan[row][col] = board[row + 1][col];
				}else {
					vungBatQuan[row][col] = board[row + 4][col + 14];	
				}
				
				vungGhiSoLuongTuBinh[row][col] = getVungGhiSoLuongTuBinh( row, vungBatQuan[row][col] );					
			}
		}

		// Vung phong quan
		for ( row = 0; row < Const.VUNG_PHONG_QUAN_ROW; row++ ) {
			for ( col = 0; col < Const.REAL_BOARD_COL; col++ ) {
				vungPhongQuanDen[row][col] = realBoard[row][col];
//				vungPhongQuanTrang[row][col] = realBoard[row + 6][col];
				vungPhongQuanTrang[row][col] = realBoard[row][col];
			}
		}

		int tenQuanTrangX = 39;
		int tenQuanDenX = 14 * kichThuocOCo.width + 22;
		int tenQuanTrangY = 5 * kichThuocOCo.height;
		int wi = 129;
		int hie = 30;

		int gapY = ( kichThuocOCo.height / 11 ) * 6;

		vungThongTinQuanTrang[0] = new Rectangle( tenQuanTrangX, tenQuanTrangY,
				wi, hie );
		vungThongTinQuanTrang[1] = new Rectangle( tenQuanTrangX, tenQuanTrangY
				+ gapY, wi, hie );
		vungThongTinQuanDen[0] = new Rectangle( tenQuanDenX, tenQuanTrangY, wi,
				hie );
		vungThongTinQuanDen[1] = new Rectangle( tenQuanDenX, tenQuanTrangY + gapY,
				wi, hie );

		// Lay vi tri dat cac nut de xem lich su van co
//		historyButtonLocation = new Point( board[Const.GLOBAL_BOARD_ROW - 1][5].x
//				+ kichThuocOCo.width / 3 * 2,
//				board[Const.GLOBAL_BOARD_ROW - 1][5].y + 20 );
		historyButtonLocation = new Point( board[Const.GLOBAL_BOARD_ROW - 1][4].x,
				board[Const.GLOBAL_BOARD_ROW - 1][5].y + 25 );

		privateChatLocation = new Point( board[0][17].x, board[0][17].y
				+ Const.DIALOG_TITLE_HEIGHT );
		//		privateChatLocation = new Point( board[0][18].x, 30 );
	}

	public Rectangle[][] getBoard() {
		return board;
	}
	
	public Rectangle[][] getActiveBoard() {
		return activeBoard;
	}
	
	public Rectangle[][] getRealBoard() {
		return realBoard;
	}

	public Rectangle[][] getVungBatQuanCuaQuanTrang() {
		return vungBatQuanCuaQuanTrang;
	}

	public Rectangle[][] getVungBatQuanCuaQuanDen() {
		return vungBatQuanCuaQuanDen;
	}

	public Rectangle[][] getVungGhiSoLuongTuBinhCuaTrang() {
		return vungGhiSoLuongTuBinhCuaQuanTrang;
	}

	public Rectangle[][] getVungGhiSoLuongTuBinhCuaDen() {
		return vungGhiSoLuongTuBinhCuaQuanDen;
	}

	public Rectangle[][] getVungPhongQuanTrang() {
		return vungPhongQuanTrang;
	}

	public Rectangle[][] getVungPhongQuanDen() {
		return vungPhongQuanDen;
	}

	public int[][] getSoLuongTuBinhCuaTrang() {
		return soLuongTuBinhCuaTrang;
	}

	public int[][] getSoLuongTuBinhCuaDen() {
		return soLuongTuBinhCuaDen;
	}

	public Rectangle[] getVungThongTinQuanTrang() {
		return vungThongTinQuanTrang;
	}

	public Rectangle[] getVungThongTinQuanDen() {
		return vungThongTinQuanDen;
	}

	@Deprecated
	public void resetSoLuongTuBinh2() {
		for ( int row = 0; row < Const.VUNG_BAT_QUAN_ROW; row++ ) {
			for ( int col = 0; col < Const.VUNG_BAT_QUAN_COL; col++ ) {
				soLuongTuBinhCuaTrang[row][col] = 0;
				soLuongTuBinhCuaDen[row][col] = 0;
			}
		}
	}
	
	public void resetSoLuongTuBinh() {
		for ( int row = 0; row < 6; row++ ) {
			for ( int col = 0; col < Const.VUNG_BAT_QUAN_COL; col++ ) {
				soLuongTuBinh[row][col] = 0;
			}
		}
	}
	
	/**
	 * 
	 * @param toaDo x = row, y = col
	 */
	public void tangSoLuongTuBinh( Point toaDo ) {
		soLuongTuBinh[toaDo.x][toaDo.y]++;
	}
	
	public void giamSoLuongTuBinh( Point toaDo ) {
		soLuongTuBinh[toaDo.x][toaDo.y]--;
	}
	
	public Point getToaDoNhaTu( Rectangle rect ) {
		Point point = new Point( Const.UNDEFINE_VALUE, Const.UNDEFINE_VALUE );
		for( int row = 0; row < 6; row++ ) {
			for( int col = 0; col < Const.VUNG_BAT_QUAN_COL; col++ ) {
				if( vungBatQuan[row][col].x == rect.x && vungBatQuan[row][col].y == rect.y ) {
					point.x = row;
					point.y = col;
				}
			}
		}
		
		if( point.x == Const.UNDEFINE_VALUE || point.y == Const.UNDEFINE_VALUE ) {
			throw new RuntimeException();
		}
		
		return point;
	}
	
	private Rectangle getVungGhiSoLuongTuBinh( int row, Rectangle oGiuQuan ) {
		int x, y;
		if( row < 3 ) {
			x = oGiuQuan.x + oGiuQuan.width * 5 / 51;
			y = oGiuQuan.y + oGiuQuan.height * 48 / 55;
		}else {
			x = oGiuQuan.x + oGiuQuan.width * 15 / 17;
			y = oGiuQuan.y + oGiuQuan.height * 8 / 55;
		}
		
		return new Rectangle( x, y, oGiuQuan.width * 5 / 51,
				oGiuQuan.height * 7 / 55 );
	}

	private Rectangle getVungGhiSoLuongTuBinhCuaQuanDen( Rectangle oGiuQuan ) {
		int x = oGiuQuan.x + oGiuQuan.width * 15 / 17;
		int y = oGiuQuan.y + oGiuQuan.height * 8 / 55;

		return new Rectangle( x, y, oGiuQuan.width * 2 / 17,
				oGiuQuan.height * 8 / 55 );
	}

	private Rectangle getVungGhiSoLuongTuBinhCuaQuanTrang( Rectangle oGiuQuan ) {
		int x = oGiuQuan.x + oGiuQuan.width * 5 / 51;
		int y = oGiuQuan.y + oGiuQuan.height * 48 / 55;

		return new Rectangle( x, y, oGiuQuan.width * 5 / 51,
				oGiuQuan.height * 7 / 55 );
	}

	public Rectangle getODangChon( int x, int y ) {
		int row = 0, col = 0;
		for ( row = 0; row < Const.GLOBAL_BOARD_ROW; row++ ) {
			for ( col = 0; col < Const.GLOBAL_BOARD_COL; col++ ) {
				if ( board[row][col].contains( x, y ) ) {
					return board[row][col];
				}
			}
		}

		return null;
	}

	/**
	 * Get the rectangle in board that contain x, y cooidinate
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	public Rectangle getRect( int x, int y ) {
		int row = 0, col = 0;
		for ( row = 0; row < Const.GLOBAL_BOARD_ROW; row++ ) {
			for ( col = 0; col < Const.GLOBAL_BOARD_COL; col++ ) {
				if ( board[row][col].contains( x, y ) ) {
					return board[row][col];
				}
			}
		}

		return null;
	}

	public Rectangle getRectInRealBoard( int x, int y ) {
		int row = 0, col = 0;
		for ( row = 0; row < Const.REAL_BOARD_ROW; row++ ) {
			for ( col = 0; col < Const.REAL_BOARD_COL; col++ ) {
				if ( realBoard[row][col].contains( x, y ) ) {
					return realBoard[row][col];
				}
			}
		}

		return null;
	}

	public Rectangle makeSymmetry( int row, int col ) {
		row = 2 * Const.SYMMETRY_POINT.x - row;
		col = 2 * Const.SYMMETRY_POINT.y - col;

		return activeBoard[row][col];
	}

	public Rectangle makeSymmetry( Rectangle rect ) {
		int row = RectangleUtils.convertToActiveBoardRow( rect );
		int col = RectangleUtils.convertToActiveBoardCol( rect );

		return makeSymmetry( row, col );
	}

	//	public Rectangle getUndefineRect() {
	//		return new Rectangle( UNDEFINE_X_Y, UNDEFINE_X_Y, kichThuocOCo.width, kichThuocOCo.height );
	//	}

	public Point getHistoryButtonLocation() {
		return historyButtonLocation;
	}

	public Point getPrivateChatLocation() {
		return privateChatLocation;
	}

	@Deprecated
	public boolean isInRealBoard( MouseEvent event ) {
		int x = event.getX();
		int y = event.getY();

		return isInRealBoard( x, y );		
	}
	
	public boolean isInRealBoard( int x, int y ) {
		int row = 0, col = 0;
		for ( row = 0; row < Const.REAL_BOARD_ROW; row++ ) {
			for ( col = 0; col < Const.REAL_BOARD_COL; col++ ) {
				if ( realBoard[row][col].contains( x, y ) ) {
					return true;
				}
			}
		}

		return false;
	}

	public boolean isInRealBoard( Rectangle rect ) {
		int row = 0, col = 0;
		for ( row = 0; row < Const.REAL_BOARD_ROW; row++ ) {
			for ( col = 0; col < Const.REAL_BOARD_COL; col++ ) {
				if ( realBoard[row][col] == rect ) {
					return true;
				}
			}
		}
		return false;
	}

	public boolean isInUpgradeZone( Rectangle destination, int color ) {

		for ( int row = 0; row < Const.VUNG_PHONG_QUAN_ROW; row++ ) {
			for ( int col = 0; col < Const.REAL_BOARD_COL; col++ ) {
				if ( vungPhongQuanTrang[row][col] == destination ) {
					if ( color == QuanCo.QUAN_TRANG ) {
						return true;
					}
				}
				if ( vungPhongQuanDen[row][col] == destination ) {
					if ( color == QuanCo.QUAN_DEN ) {
						return true;
					}
				}
			}
		}

		return false;
	}

	public boolean isInVungCamThaQuanLoai1( Rectangle destination, int color ) {
		int row = 0;
//		if ( color == QuanCo.QUAN_TRANG ) {
//			row = 8;
//		}

		for ( int col = 0; col < Const.REAL_BOARD_COL; col++ ) {
			if ( realBoard[row][col] == destination ) {
				return true;
			}
		}

		return false;
	}

	public boolean isInVungCamThaQuanLoai2( Rectangle destination, int color ) {

		if ( isInVungCamThaQuanLoai1( destination, color ) ) {
			return true;
		}

		int row = 1;
//		if ( color == QuanCo.QUAN_TRANG ) {
//			row = 7;
//		}

		for ( int col = 0; col < Const.REAL_BOARD_COL; col++ ) {
			if ( realBoard[row][col] == destination ) {
				return true;
			}
		}

		return false;
	}
	
	@Deprecated
	public boolean isInPrison( int x, int y ) {
		int row = 0, col = 0;
		for ( row = 0; row < Const.VUNG_BAT_QUAN_ROW; row++ ) {
			for ( col = 0; col < Const.VUNG_BAT_QUAN_COL; col++ ) {
				if ( vungBatQuanCuaQuanDen[row][col].contains( x, y ) ||
						vungBatQuanCuaQuanTrang[row][col].contains( x, y )	) {
					return true;
				}
			}
		}

		return false;
	}

	//	public boolean isInInvalidArea( Rectangle rect ) {
	//		
	//		if( !isInRealBoard( rect ) ) {
	//			int row = 0, col = 0;
	//			for( row = 0; row < 3; row ++ ) {
	//				for( col = 0; col < 3; col++ ) {
	//					if( vungBatQuanCuaQuanTrang[row][col] != rect && vungBatQuanCuaQuanDen[row][col] != rect ) {
	//						return true;
	//					}				
	//				}
	//			}
	//		}
	//		
	//		return false;
	//	}

	@Deprecated
	public void veVungBatQuan( Graphics g ) {
		g.setColor( Color.BLUE );
		int soLuongTrang = 0;
		int soLuongDen = 0;
		for ( int row = 0; row < Const.VUNG_BAT_QUAN_ROW; row++ ) {
			for ( int col = 0; col < Const.VUNG_BAT_QUAN_COL; col++ ) {
				soLuongDen = soLuongTuBinhCuaDen[row][col];
				if ( soLuongDen > 1 ) {
					g.drawString( String.valueOf( soLuongDen ), vungGhiSoLuongTuBinhCuaQuanDen[row][col].x, vungGhiSoLuongTuBinhCuaQuanDen[row][col].y );
				}
				soLuongTrang = soLuongTuBinhCuaTrang[row][col];
				if ( soLuongTrang > 1 ) {
					g.drawString( String.valueOf( soLuongTrang ), vungGhiSoLuongTuBinhCuaQuanTrang[row][col].x, vungGhiSoLuongTuBinhCuaQuanTrang[row][col].y );
				}

				//				g.drawRect( vungBatQuanCuaQuanTrang[row][col].x, vungBatQuanCuaQuanTrang[row][col].y, vungBatQuanCuaQuanTrang[row][col].width, vungBatQuanCuaQuanTrang[row][col].height );
				//				g.drawRect( vungBatQuanCuaQuanDen[row][col].x, vungBatQuanCuaQuanDen[row][col].y, vungBatQuanCuaQuanDen[row][col].width, vungBatQuanCuaQuanDen[row][col].height );
			}
		}
	}
	
	public void veVungBatQuan2( Graphics g ) {
		g.setColor( Color.BLUE );
		for ( int row = 0; row < 6; row++ ) {
			for ( int col = 0; col < Const.VUNG_BAT_QUAN_COL; col++ ) {
//				g.drawRect(vungBatQuan[row][col].x, vungBatQuan[row][col].y, vungBatQuan[row][col].width, vungBatQuan[row][col].height );
				if( soLuongTuBinh[row][col] > 1 ) {
					g.drawString( String.valueOf( soLuongTuBinh[row][col] ), vungGhiSoLuongTuBinh[row][col].x, vungGhiSoLuongTuBinh[row][col].y );	
				}
				
			}
		}
	}

	public Rectangle getMessageArea() {
		return new Rectangle( realBoard[4][2].x, realBoard[4][2].y,
				realBoard[4][2].width * 5, realBoard[4][2].width );
	}

	/**
	 * @param g
	 * @param message Tham khao:
	 *            http://download.oracle.com/javase/tutorial/2d/text
	 *            /measuringtext.html
	 */
	public void drawMessage( Graphics g, String message ) {

		// Check null
		if ( message == null ) {
			return;
		}

		Rectangle rect = getMessageArea();

		Font font = new Font( "Verdana", 1, 10 );
		FontMetrics metrics = g.getFontMetrics( font );
		int textSize = metrics.stringWidth( message );

		g.setColor( Color.RED );
		g.fillRect( rect.x, rect.y, rect.width, rect.height );
		g.setColor( Color.WHITE );
		g.drawRect( rect.x, rect.y, rect.width, rect.height );
		g.drawString( message, rect.x + ( rect.width - textSize ) / 2, rect.y
				+ rect.height / 2 );
	}

//	public void increaseSoluongTuBinh( Rectangle rect, int color ) {
//		int[][] soLuongTuBinh;
//		Rectangle[][] vungBatQuan;
//
//		if ( color == QuanCo.QUAN_DEN ) {
//			vungBatQuan = vungBatQuanCuaQuanDen;
//			soLuongTuBinh = soLuongTuBinhCuaDen;
//		} else {
//			vungBatQuan = vungBatQuanCuaQuanTrang;
//			soLuongTuBinh = soLuongTuBinhCuaTrang;
//		}
//
//		for ( int row = 0; row < Const.VUNG_BAT_QUAN_ROW; row++ ) {
//			for ( int col = 0; col < Const.VUNG_BAT_QUAN_COL; col++ ) {
//				if ( vungBatQuan[row][col] == rect ) {
//					soLuongTuBinh[row][col]++;
//					return;
//				}
//			}
//		}
//	}

	public int[] getToaDoNhaTu( Rectangle[][] vungBatQuan, Rectangle rect ) {
		int[] value = new int[2];

		for ( int row = 0; row < Const.VUNG_BAT_QUAN_ROW; row++ ) {
			for ( int col = 0; col < Const.VUNG_BAT_QUAN_COL; col++ ) {
				if ( vungBatQuan[row][col] == rect ) {
					value[0] = row;
					value[1] = col;

					return value;
				}

			}
		}

		return value;
	}
	
	public ArrayList<Rectangle> getRepaintOnlyActiveBoard(){
		ArrayList<Rectangle> list = new ArrayList<Rectangle>();
		for ( int row = 0; row < Const.ACTIVE_BOARD_ROW - 1; row++ ) {
			for ( int col = 0; col < Const.ACTIVE_BOARD_COL; col++ ) {
				list.add( activeBoard[row][col] );
			}
		}
		
		return list;
	}
	
	public Dimension getPrivateChatAreaSize() {
		int w = boardSize.width / Const.GLOBAL_BOARD_COL * 4;
		int h = boardSize.height / Const.GLOBAL_BOARD_ROW * 6;
		
		return new Dimension( w, h);
	}

}
